/****************************************************
	文件：StrategyPatternPlus.cs
	作者：HuskyT
	邮箱：1005240602@qq.com
	日期：2020/5/3 18:32:22
	功能：策略模式And抽象工厂And反射And缓存（策略模式的扩展，处理不同情况下选择不同计算策略）
*****************************************************/

using System;
using System.Collections.Generic;
using UnityEngine;

namespace DesignPatterns
{
    public class StrategyPatternPlus : MonoBehaviour
    {
        private void Start()
        {
            //策略模式And抽象工厂And反射And缓存：
            //策略模式的终极状态！
            //通过工厂模式封装不同情况下的策略选择
            //使用反射去除分支判断
            //使用缓存减少反射带来的性能消耗

            CharacterAttributes player = new CharacterAttributes { Atk = 10, Def = 4, Pierce = 6, State = CharacterState.Def_Ignore };//玩家
            CharacterAttributes enemy = new CharacterAttributes { Atk = 6, Def = 3, Pierce = 4, State = CharacterState.Normal };//敌人
            StrategyFactory factory = new StrategyFactory(true);
            float damage = factory.GetResult(player, enemy);
            Debug.LogFormat("计算玩家对敌人造成伤害为：{0}", damage);//16
            damage = factory.GetResult(enemy, player);
            Debug.LogFormat("计算敌人对玩家造成伤害为：{0}", damage);//4
        }

        /// <summary>
        /// 策略工厂（反射+缓存）
        /// </summary>
        public class StrategyFactory
        {
            public static string NAME_SPACE = "DesignPatterns";
            private static Dictionary<CharacterState, StrategyBase> mStrategyDict;
            public StrategyFactory(bool cacheAll)
            {
                mStrategyDict = new Dictionary<CharacterState, StrategyBase>();
                if (cacheAll)//缓存
                {
                    foreach (CharacterState characterState in Enum.GetValues(typeof(CharacterState)))
                    {
                        TryAddToCache(characterState);
                    }
                }
            }
            public float GetResult(params CharacterAttributes[] args)
            {
                if (args.Length <= 1) return 0.0f;
                return GetFromCache(args[0].State).GetResult(args);
            }
            public void ClearCache()
            {
                mStrategyDict.Clear();
                mStrategyDict = null;
            }
            private StrategyBase GetFromCache(CharacterState characterState)
            {
                TryAddToCache(characterState);
                return mStrategyDict[characterState];
            }
            private void TryAddToCache(CharacterState characterState)
            {
                if (mStrategyDict.ContainsKey(characterState) && mStrategyDict[characterState] != null) return;
                mStrategyDict[characterState] = Create<StrategyBase>(characterState.ToString());
            }
            //使用反射创建对象
            private static K Create<K>(string className) where K : class
            {
                Debug.Log("反射创建对象");
                //无参：
                return Activator.CreateInstance(Type.GetType(NAME_SPACE + ".StrategyPatternPlus+" + className)) as K;

                //有参：
                //return Activator.CreateInstance(Type.GetType(NAME_SPACE + ".StrategyPatternPlus+" + className), new object()) as T;
            }
        }
        /// <summary>
        /// 策略基类
        /// </summary>
        public abstract class StrategyBase
        {
            public abstract float GetResult(params CharacterAttributes[] args);
        }
        /// <summary>
        /// 计算伤害（策略A）
        /// 通常情况下的计算方式
        /// </summary>
        public class Normal : StrategyBase
        {
            public override float GetResult(params CharacterAttributes[] args)
            {
                if (args.Length <= 1) return 0.0f;
                CharacterAttributes attacker = args[0];
                CharacterAttributes defender = args[1];
                float damage = attacker.Atk - defender.Def + attacker.Pierce * 0.5f;
                return damage;
            }
        }
        /// <summary>
        /// 计算伤害（策略B）
        /// 穿刺加成状态下的计算方式
        /// </summary>
        public class Pierce_Add : StrategyBase
        {
            public override float GetResult(params CharacterAttributes[] args)
            {
                if (args.Length <= 1) return 0.0f;
                CharacterAttributes attacker = args[0];
                CharacterAttributes defender = args[1];
                float damage = attacker.Atk - defender.Def + attacker.Pierce;
                return damage;
            }
        }
        /// <summary>
        /// 计算伤害（策略C）
        /// 无视防御状态下的计算方式
        /// </summary>
        public class Def_Ignore : StrategyBase
        {
            public override float GetResult(params CharacterAttributes[] args)
            {
                if (args.Length <= 1) return 0.0f;
                CharacterAttributes attacker = args[0];
                CharacterAttributes defender = args[1];
                float damage = attacker.Atk + attacker.Pierce;
                return damage;
            }
        }

        /// <summary>
        /// 角色属性
        /// </summary>
        public class CharacterAttributes
        {
            public float Atk;
            public float Def;
            public float Pierce;//穿刺伤害
            public CharacterState State;//角色状态
        }
        /// <summary>
        /// 角色状态（不同的状态对应不同的计算策略）
        /// </summary>
        public enum CharacterState
        {
            Normal,
            Pierce_Add,
            Def_Ignore,
        }
    }
}